home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / shell / csh535src.lha / comm3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-14  |  52.8 KB  |  2,706 lines

  1. /*
  2.  * COMM3.C
  3.  *
  4.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  5.  * Version 5.00L by Urban Mueller 17-Feb-91
  6.  * Version 5.20L by Andreas M. Kirchwitz (Fri, 13 Mar 1992)
  7.  *
  8.  */
  9.  
  10. #include "shell.h"
  11.  
  12. /* comm3.c */
  13. static void doassign(char *log, char *phy);
  14. static void assignlist(void);
  15. static int strings_in_file(long mask, char *s, char *path);
  16. static int htype_a_file   (long mask, char *s, char *path);
  17. static void install_menu(char **mav, int mac);
  18. static int line_filter( char *(*line)(char *) );
  19.  
  20.  
  21. /* Casting conveniences */
  22. #define BPTR_TO_C(strtag, var)  ((struct strtag *)(BADDR( (ULONG) var)))
  23. #define PROC(task)              ((struct Process *)task)
  24. #define CLI(proc)               (BPTR_TO_C(CommandLineInterface, proc->pr_CLI))
  25.  
  26.  
  27. int do_ln(void)
  28. {
  29.     char *linkname;
  30.     long link_type;
  31.     long dest_data;
  32.     BOOL success;
  33.  
  34.     if( ac!=2 && ac!=3 ) {
  35.         show_usage( NULL );
  36.         return 20;
  37.     }
  38.  
  39.     if (ac==2)
  40.         linkname = FilePart(av[1]);
  41.     else
  42.         linkname = av[2];
  43.  
  44.     if (options&1) {
  45.         link_type = LINK_SOFT;
  46.         dest_data = (long)av[1];
  47.     }
  48.     else {
  49.         link_type = LINK_HARD;
  50.         if (!( dest_data = (long)Lock(av[1],ACCESS_READ) )) {
  51.             pError(av[1]);
  52.             return 20;
  53.         }
  54.     }
  55.  
  56.     success = MakeLink(linkname,dest_data,link_type);
  57.  
  58.     if (link_type==LINK_HARD)
  59.         UnLock((BPTR)dest_data);
  60.  
  61.     if (!success) {
  62.         pError(linkname);
  63.         return 20;
  64.     }
  65.  
  66.     return 0;
  67. }
  68.  
  69.  
  70. do_tee( void )
  71. {
  72.     char buf[256];
  73.     FILE *out;
  74.  
  75.     prepscroll( ac==1 );
  76.     if( ac>2 ) { ierror( av[2], 500 ); return 20; }
  77.     if( ac==1 ) out=stderr;
  78.     else if( !(out=fopen( av[1], "w" ))) { pError( av[1] ); return 20; }
  79.     while (safegets(buf,stdin)) {
  80.         puts(buf);
  81.         quickscroll();
  82.         fprintf(out,"%s\n",buf);
  83.     }
  84.     if( ac!=1 ) fclose( out );
  85.     return 0;
  86. }
  87.  
  88. do_head( char *garbage, int com )
  89. {
  90.     FILE *f;
  91.     int i, n = 10;
  92.     char buf[256];
  93.  
  94.     if (ac==1) {                    /* use stdin */
  95.         f = stdin;
  96.     }
  97.     else {
  98.         f=fopen(av[1],"r");
  99.         if (f==NULL) {
  100.             if (ac==2 && isnum(av[1])) {    /* use stdin */
  101.                 f = stdin;
  102.                 n = atol(av[1]);
  103.             }
  104.             else {
  105.                 pError(av[1]);
  106.                 return 20;
  107.             }
  108.         }
  109.     }
  110.  
  111.     if (ac>2) {
  112.         if (!isnum(av[2])) {   /* AMK: IoErr() replaced by isnum() */
  113.             ierror(av[2],511);
  114.             return 20;
  115.         }
  116.         n=(int)atol(av[2]);
  117.     }
  118.  
  119.     if (com) {    /* tail specific part */
  120.         i=0;
  121.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  122.         rewind(f);
  123.         if (n>i) n=i;
  124.         i=i-n;
  125.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  126.     }
  127.  
  128.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  129.         printf("%s", buf);
  130.  
  131.     if (f!=stdin)
  132.         fclose(f);
  133.  
  134.     return 0;
  135. }
  136.  
  137. #if 0
  138. do_head( char *garbage, int com )
  139. {
  140.     int i, n;
  141.     FILE *f;
  142.     char buf[256];
  143.  
  144.     if (ac>2) {
  145.         if (!isnum(av[2])) {   /* AMK: IoErr() replaced by isnum() */
  146.             ierror(av[2],511);
  147.             return 20;
  148.         }
  149.         n=(int)atol(av[2]);
  150.     } else n=10;
  151.  
  152.     f=fopen(av[1], "r");
  153.     if (f==NULL) {
  154.         pError(av[1]);
  155.         return 20;
  156.     }
  157.     if (com) {    /* tail specific part */
  158.         i=0;
  159.         while (fgets(buf, 256, f) && ! dobreak()) i++;
  160.         rewind(f);
  161.         if (n>i) n=i;
  162.         i=i-n;
  163.         while (i-- && fgets(buf, 256, f) && ! dobreak()) ;
  164.     }
  165.     for (i=1; i<=n && fgets(buf, 256, f) && ! dobreak(); i++)
  166.         printf("%s", buf);
  167.     fclose(f);
  168.     return 0;
  169. }
  170. #endif
  171.  
  172. static int
  173. exword( char **src, char *buf )
  174. {
  175.     *buf=0;
  176.     if( **src==0 ) return 0;
  177.     while( **src && **src!=0xA0 )
  178.         *buf++=*(*src)++;
  179.     *buf=0;
  180.     if( **src ) (*src)++;
  181.     return 1;
  182. }
  183.  
  184. static char helpfound=0;
  185.  
  186. void
  187. man (FILE *f, char *s)
  188. {
  189.     char buf[140], entry[100];
  190.     int  len = sprintf (entry, "    %s", s);
  191.     char *example = "    ";
  192.  
  193.     prepscroll (0);
  194.     rewind (f);
  195.     do {                        /* look for required argument */
  196.         if (fgets (buf, sizeof(buf), f)==NULL || dobreak())
  197.             return;                /* GMD */
  198.     } while (strnicmp (entry, buf, len)) ;
  199.     helpfound = 1;
  200.  
  201.     do {                /* display help */
  202.         if (dobreak())
  203.             return;
  204.         quickscroll ();
  205.         printf ("%s", buf);
  206.         if (fgets (buf, sizeof(buf), f) == NULL)
  207.             return;
  208.     } while ((!isalphanum (*buf)) && strncmp (buf, example, strlen(example))) ;
  209. }
  210.  
  211.  
  212. do_man( void )
  213. {
  214.     FILE *f;
  215.     int i;
  216.     char buf[200], name[60], *src, *var, docfound=0;
  217.  
  218.     buf[0]=0;
  219.     if( var=get_var(LEVEL_SET,"_man" ) )
  220.         strcpy(buf,var);
  221.  
  222.     if (ac==1) ac=2, av[1]="MAN";
  223.     for (i=1; i<ac; i++) {
  224.         src=buf, helpfound=0;
  225.         while( exword( &src, name) )
  226.             if( f=fopen(name, "r") ) {
  227.                 docfound=1;
  228.                 man(f, av[i]);
  229.                 fclose(f);
  230.                 if( helpfound )
  231.                     break;
  232.             }
  233.         if( !docfound )
  234.             fprintf(stderr,"%s not found\n",buf);
  235.         else if( !helpfound )
  236.             fprintf(stderr, "Help not found for %s\n", av[i]);
  237.     }
  238.     return 0;
  239. }
  240.  
  241. do_assign( void )
  242. {
  243.     int i;
  244.  
  245.     if     (  ac==1  ) assignlist();
  246.     else if(  ac==2  ) doassign(av[1], NULL);
  247.     else if( !(ac&1) ) ierror(NULL, 500);
  248.     else
  249.         for( i=1; i<ac; i+=2 )
  250.             doassign( av[i],av[i+1] );
  251.     return 0;
  252. }
  253.  
  254. /* AMK: rewritten code, removed bug when strlen(log) was 0 */
  255. static void
  256. doassign(char *log, char *phy)
  257. {
  258.     int last=strlen(log);
  259.  
  260.     if (last<2 || log[last-1] != ':') fprintf(stderr, "Bad name %s\n", log);
  261.     else {
  262.         int succ=0;
  263.  
  264.         log[last-1] = 0;
  265.  
  266.         if (!phy)
  267.             succ=AssignLock(log,NULL);
  268.         else if (options&1) {   /* add assign, CLI: assign ADD */
  269.             BPTR lock;
  270.             if( lock=Lock(phy,ACCESS_READ) )
  271.                 if( !(succ=AssignAdd(log,lock)))
  272.                     UnLock(lock);
  273.         }
  274.  
  275.         /* late-binding assign, CLI: assign DEFER */
  276.         else if (options&2 || options&8)
  277.             succ=AssignLate(log,phy);
  278.  
  279.         /* non-binding assign, CLI: assign PATH */
  280.         else if (options&4 || options&16)
  281.             succ=AssignPath(log,phy);
  282.         else if (!options) {
  283.             BPTR lock;
  284.             if( lock=Lock(phy,ACCESS_READ) )
  285.                 if( !(succ=AssignLock(log,lock)))
  286.                     UnLock(lock);
  287.         }
  288.  
  289.         if( !succ )
  290.             pError( log );
  291.     }
  292. }
  293.  
  294.  
  295. static void
  296. assignlist()
  297. {
  298.     char *ptr;
  299.     struct DosList *dl;
  300.     struct AssignList *path;
  301.     ULONG flags;
  302.     char fmt[256],devname[256];
  303.     char **dev_list;
  304.     long dev_num,i,cnt;
  305.  
  306.     dev_list = NULL;
  307.     dev_num  = 0;
  308.     flags    = LDF_VOLUMES|LDF_READ;
  309.  
  310.     if (dl=LockDosList(flags)) {
  311.         while (dl=NextDosEntry(dl,flags)) {
  312.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  313.             sprintf(fmt,"%s%s",devname,
  314.                     dl->dol_misc.dol_volume.dol_LockList?"":" [Mounted]");
  315.             add_array_list(&dev_list,&dev_num,fmt);
  316.         }
  317.         UnLockDosList(flags);
  318.     }
  319.  
  320.     QuickSort(dev_list,dev_num);
  321.     printf("Volumes:\n");
  322.     for(i=0; i<dev_num; i++)
  323.         printf("%s\n",dev_list[i]);
  324.     free_array_list(dev_list,dev_num);
  325.  
  326.     if (dobreak())
  327.         return;
  328.  
  329.     dev_list = NULL;
  330.     dev_num  = 0;
  331.     flags    = LDF_ASSIGNS|LDF_READ;
  332.  
  333.     if (dl=LockDosList(flags)) {
  334.         while (dl=NextDosEntry(dl,flags)) {
  335.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  336.  
  337.             sprintf(fmt,"%-14s ",devname);
  338.             ptr = fmt+strlen(fmt);
  339.  
  340.             switch (dl->dol_Type) {
  341.                 case DLT_DIRECTORY :
  342.                     if(dl->dol_Lock)
  343.                         NameFromLock(dl->dol_Lock,ptr,200L);
  344.                     else
  345.                         strcpy(ptr,"Nonexisting lock");
  346. /* --- */
  347.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  348.                         char **ass_list=NULL;
  349.                         long ass_num=0,str_len=0;
  350.                         char *ass_str;
  351.  
  352.                         add_array_list(&ass_list,&ass_num,fmt);
  353.                         str_len += strlen(fmt);
  354.  
  355.                         for (; path; path=path->al_Next) {
  356.                             sprintf(fmt,"%-13s+ ","");
  357.                             ptr = fmt+strlen(fmt);
  358.                             if (dl->dol_Lock)
  359.                                 NameFromLock(path->al_Lock,ptr,200L);
  360.                             else
  361.                                 strcpy(ptr,"Nonexisting lock");
  362.                             add_array_list(&ass_list,&ass_num,fmt);
  363.                             str_len += strlen(fmt)+1;
  364.                         }
  365.  
  366.                         if (ass_str=malloc(str_len+1)) {
  367.                             char *p=ass_str;
  368.                             for(i=0; i<ass_num; i++) {
  369.                                 strcpy(p,ass_list[i]);
  370.                                 p += strlen(p);
  371.                                 if ((i+1)<ass_num) {
  372.                                     *p++ = '\n';
  373.                                     *p   = '\0';
  374.                                 }
  375.                             }
  376.                             add_array_list(&dev_list,&dev_num,ass_str);
  377.                             free(ass_str);
  378.                         }
  379.  
  380.                         free_array_list(ass_list,ass_num);
  381.                     }
  382.                     else
  383.                         add_array_list(&dev_list,&dev_num,fmt);
  384. /* --- */
  385. #if 0
  386.                     add_array_list(&dev_list,&dev_num,fmt);
  387.  
  388.                     for(path=dl->dol_misc.dol_assign.dol_List; path; path=path->al_Next) {
  389.                         sprintf(fmt,"%-13s+ ","");
  390.                         ptr = fmt+strlen(fmt);
  391.                         if (dl->dol_Lock)
  392.                             NameFromLock(path->al_Lock,ptr,200L);
  393.                         else
  394.                             strcpy(ptr,"Nonexisting lock");
  395.                         add_array_list(&dev_list,&dev_num,fmt);
  396.                     }
  397. #endif
  398.                     break;
  399.                 case DLT_LATE      :
  400.                     sprintf(ptr,"<%s>",dl->dol_misc.dol_assign.dol_AssignName);
  401.                     add_array_list(&dev_list,&dev_num,fmt);
  402.                     break;
  403.                 case DLT_NONBINDING:
  404.                     sprintf(ptr,"[%s]",dl->dol_misc.dol_assign.dol_AssignName);
  405.                     add_array_list(&dev_list,&dev_num,fmt);
  406.                     break;
  407.                 default:
  408.                     strcpy(ptr,"Unknown assign");
  409.                     add_array_list(&dev_list,&dev_num,fmt);
  410.                     break;
  411.             }
  412.         }
  413.         UnLockDosList(flags);
  414.     }
  415.  
  416.     QuickSort(dev_list,dev_num);
  417.     printf("\nDirectories:\n");
  418.     for(i=0; !dobreak() && i<dev_num; i++)
  419.         printf("%s\n",dev_list[i]);
  420.     free_array_list(dev_list,dev_num);
  421.  
  422.     if (dobreak())
  423.         return;
  424.  
  425.     dev_list = NULL;
  426.     dev_num  = 0;
  427.     flags    = LDF_DEVICES|LDF_READ;
  428.  
  429.     if (dl=LockDosList(flags)) {
  430.         while (dl=NextDosEntry(dl,flags)) {
  431.             if (dl->dol_Task) {
  432.                 BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  433.                 add_array_list(&dev_list,&dev_num,devname);
  434.             }
  435.         }
  436.         UnLockDosList(flags);
  437.     }
  438.  
  439.     QuickSort(dev_list,dev_num);
  440.     printf("\nDevices (with FileSystem):\n");
  441.     for(i=0,cnt=0; i<dev_num; i++) {
  442.         if (IsFileSystem(dev_list[i])) {
  443.             if (cnt>0 && cnt%5==0)
  444.                 printf("\n");
  445.             printf("%s ",dev_list[i]);
  446.             ++cnt;
  447.         }
  448.     }
  449.     printf("\n");
  450.     free_array_list(dev_list,dev_num);
  451.  
  452.     if (dobreak())
  453.         return;
  454.  
  455.     dev_list = NULL;
  456.     dev_num  = 0;
  457.     flags    = LDF_DEVICES|LDF_READ;
  458.  
  459.     if (dl=LockDosList(flags)) {
  460.         while (dl=NextDosEntry(dl,flags)) {
  461.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  462.             add_array_list(&dev_list,&dev_num,devname);
  463.         }
  464.         UnLockDosList(flags);
  465.     }
  466.  
  467.     QuickSort(dev_list,dev_num);
  468.     printf("\nDevices:\n");
  469.     for(i=0; i<dev_num; i++) {
  470.         if (i>0 && i%5==0)
  471.             printf("\n");
  472.         printf("%s ",dev_list[i]);
  473.     }
  474.     printf("\n");
  475.     free_array_list(dev_list,dev_num);
  476.  
  477. return;
  478. #if 0
  479.     printf("\nDirectories:\n");
  480.     for( ; arr[i] && !dobreak(); i++ ) {
  481.         log=arr[i]+1; ptr=log+strlen(log)+1;
  482.         switch( *(log-1)) {
  483.         case 3:
  484.             printf("%-20s%s\n", log, ptr);
  485.             for(;;) {
  486.                 ptr+=strlen(ptr)+1;
  487.                 if( !*ptr ) break;
  488.                     printf("%-19s+%s\n", "", ptr);
  489.             }
  490.             break;
  491.         case 4: printf("%-20s<%s>\n", log, ptr); break;
  492.         case 5: printf("%-20s[%s]\n", log, ptr); break;
  493.         }
  494.     }
  495. #endif
  496. }
  497.  
  498.  
  499.  
  500. do_join( void )
  501. {
  502.     BPTR sou, dest;
  503.     char *buffer;
  504.     int i;
  505.     long n;
  506.     char *namedest=av[--ac];
  507.  
  508.     if (options==0 && exists(namedest)) { ierror(namedest,203); return 20; }
  509.     if ( (buffer=malloc(8192)) == NULL ) { ierror(NULL,103); return 20; }
  510.     if ( (dest=Open(namedest, MODE_NEWFILE)) == NULL )
  511.         { pError(namedest); goto fail1; }
  512.     for (i=1; i<ac; i++) {
  513.         if ( (sou=Open(av[i], MODE_OLDFILE)) == NULL ) pError(av[i]);
  514.         else
  515.             while( (n=Read(sou, buffer, 8192L)) > 0 )
  516.                 if (Write(dest, buffer, n) != n)
  517.                     { pError(namedest); Close(sou); goto fail2; }
  518.         Close(sou);
  519.     }
  520. fail2:
  521.     Close(dest);
  522. fail1:
  523.     free(buffer);
  524.     return 0;
  525. }
  526.  
  527. #define BUFDIM 512L
  528. #define MAXSTR 256
  529.  
  530. int minstr;
  531.  
  532. static int
  533. strings_in_file(long mask, char *s, char *path)
  534. {
  535.     long n,i;
  536.     char c;
  537.     char readbuf[BUFDIM+1], strbuf[MAXSTR+1];
  538.     BPTR fh;
  539.     int strctr=0;
  540.     BOOL out, hdout = TRUE;  /* hdout = header output */
  541.     BOOL usestdin = (s==NULL);
  542.     BOOL inter = IsInteractive(Output());
  543.  
  544.     prepscroll(0);
  545.  
  546.     if (usestdin)
  547.         fh = Input();
  548.     else
  549.         fh = Open(s,MODE_OLDFILE);
  550.  
  551.     if (fh) {
  552.         while ( (n=Read(fh, readbuf, BUFDIM))>0 && !CHECKBREAK() )
  553.             for (i=0; i<n && !CHECKBREAK(); i++) {   /* GMD: speed up ^C reaction */
  554.                 c=readbuf[i];
  555.                 if (c<0x20 || c>0x7f) {
  556.                     out=(strctr>=minstr);
  557.                     if (!out) strctr=0;
  558.                 } else {
  559.                     strbuf[strctr++]=c;
  560.                     out=(strctr>=BUFDIM);
  561.                 }
  562.                 if (out) {
  563.                     strbuf[strctr]='\0';
  564.                     if (options&8 && hdout) {
  565.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  566.                             hdout=FALSE;
  567.                     }
  568.                     printf("%s%s%s%s%s\n",
  569.                         (options&4) ? (path?path:"STDIN") : "",
  570.                         (options&4) ? ": " : "",
  571.                         (options&2) ? "|" : "",
  572.                         strbuf,
  573.                         (options&2) ? "|" : "");
  574. #if 0
  575.                     if (options&2) {
  576.                         printf("%s: |%s|\n",path?path:"STDIN",strbuf);
  577.                     }
  578.                     else {
  579.                         if (hdout) {
  580.                             printf("Strings in %s (len>=%d):\n",path?path:"STDIN",minstr);
  581.                             hdout=FALSE;
  582.                         }
  583.                         puts(strbuf);
  584.                     }
  585. #endif
  586.                     if (inter) fflush(stdout);
  587.                     quickscroll();
  588.                     strctr=0;
  589.                 }
  590.             }
  591.         /* only close file if not standard input */
  592.         if (!usestdin)
  593.             Close(fh);
  594.     } else
  595.         pError(s);
  596.  
  597.     return 0;
  598. }
  599.  
  600. do_strings( void )
  601. {
  602.     if (isnum(av[ac-1])) {
  603.         minstr = myatoi(av[--ac],1,255);
  604.         if (atoierr) {
  605.             fprintf(stderr,"Need a valid string length parameter (1-255)!\n");
  606.             return 0;
  607.         }
  608.     }
  609.     else
  610.         minstr = 4;
  611.  
  612.     if (ac<2)
  613.         strings_in_file(0, NULL, NULL);
  614.     else
  615.         all_args( strings_in_file, 0);
  616.  
  617.     return 0;
  618. }
  619.  
  620. BPTR myfile[MAXMYFILES];
  621.  
  622. do_open( void )
  623. {
  624.     long mode;
  625.     int n;
  626.  
  627.     switch (toupper(av[2][0])) {
  628.         case 'R': mode=MODE_OLDFILE; break;
  629.         case 'W': mode=MODE_NEWFILE; break;
  630.         default : ierror(NULL,500); return 1;
  631.     }
  632.     n=myatoi(av[3],0,MAXMYFILES-1); if (atoierr) return 20;
  633.     if (myfile[n]) myclose(n);
  634.     myfile[n]=Open(av[1],mode);
  635.     return myfile[n]==NULL;
  636. }
  637.  
  638. do_close( void )
  639. {
  640.     int i, n;
  641.  
  642.     if (ac==1)
  643.         for (i=1; i<MAXMYFILES; i++)
  644.             myclose(i);
  645.     for (i=1; i<ac; i++) {
  646.         n=myatoi(av[i],0,MAXMYFILES-1); if (atoierr) return 20;
  647.         myclose(n);
  648.     }
  649.     return 0;
  650. }
  651.  
  652. void
  653. myclose(int n)
  654. {
  655.     if (myfile[n]) { Close(myfile[n]); myfile[n]=NULL; }
  656. }
  657.  
  658. do_fileslist( void )
  659. {
  660.     int i, flag=0;
  661.  
  662.     printf("Open files:");
  663.     for (i=0; i<MAXMYFILES; i++)
  664.         if (myfile[i]) { printf(" %d",i); flag=1; }
  665.     if (!flag) printf(" None!");
  666.     printf("\n");
  667.     return 0;
  668. }
  669.  
  670. BPTR
  671. extOpen( char *name, long mode )
  672. {
  673.     if (name[0]=='.' && name[1]>='0' && name[1]<='9')
  674.         return myfile[atoi(name+1)];
  675.     return Open(name,mode);
  676. }
  677.  
  678.  
  679. void
  680. extClose(BPTR fh)
  681. {
  682.     int i;
  683.  
  684.     for (i=0; i<MAXMYFILES; i++)
  685.         if (myfile[i]==fh) return;
  686.     Close(fh);
  687. }
  688.  
  689. do_basename( void )
  690. {
  691.     char *res;
  692.     int  i;
  693.  
  694.     for( i=2; i<ac; i++ )
  695.         av[i]=FilePart(av[i]);
  696.     set_var(LEVEL_SET, av[1], res=compile_av(av,2,ac,0xA0,0));
  697.     free(res);
  698.     return 0;
  699. }
  700.  
  701. do_tackon( void )
  702. {
  703.     char buf[256];
  704.  
  705.     strcpy(buf, av[2]);
  706.     AddPart(buf, av[3], 256L);
  707.     set_var(LEVEL_SET, av[1], buf);
  708.     return 0;
  709. }
  710.  
  711. extern char shellres[];
  712.  
  713. do_resident( void )
  714. {
  715.     struct Segment *seg;
  716.     char buf[256],devname[256];
  717.     char **dev_list1=NULL,**dev_list2=NULL;
  718.     long dev_num1=0,dev_num2=0,i;
  719.  
  720.     if (options==0 && ac>1) options=1;
  721.     switch (options) {
  722.     case 0:
  723.         Forbid();
  724.         seg = (struct Segment *)BADDR(((struct DosInfo *)BADDR(DOSBase->dl_Root->rn_Info))->di_NetHand);
  725.         while (seg) {
  726.             BtoCStr(devname,MKBADDR(seg->seg_Name),254L);  /* 256 - '\0' + ':' */
  727.             if (seg->seg_UC >= 0) {
  728.                 sprintf(buf,"%-18s%4.1ld",devname,seg->seg_UC-1);
  729.                 add_array_list(&dev_list1,&dev_num1,buf);
  730.             }
  731.             else {
  732.                 switch (seg->seg_UC) {
  733.                 case CMD_INTERNAL:
  734.                     sprintf(buf,"%-18s%s",devname,"INTERNAL");
  735.                     add_array_list(&dev_list2,&dev_num2,buf);
  736.                     break;
  737.                 case CMD_SYSTEM:
  738. /* don't print this */ /*
  739.                     sprintf(buf,"%-18s%s",devname,"SYSTEM");
  740.                     add_array_list(&dev_list2,&dev_num2,buf);
  741. */
  742.                     break;
  743.                 case CMD_DISABLED:
  744.                     sprintf(buf,"%-18s%s",devname,"DISABLED");
  745.                     add_array_list(&dev_list2,&dev_num2,buf);
  746.                     break;
  747.                 default:
  748.                     sprintf(buf,"%-18s%s",devname,"UNKNOWN");
  749.                     add_array_list(&dev_list2,&dev_num2,buf);
  750.                     break;
  751.                 }
  752.             }
  753.             seg = (struct Segment *)BADDR(seg->seg_Next);
  754.         }
  755.         Permit();
  756.         printf("NAME              USE COUNT\n\n");
  757.  
  758.         QuickSort(dev_list1,dev_num1);
  759.         for(i=0; !dobreak() && i<dev_num1; i++)
  760.             printf("%s\n",dev_list1[i]);
  761.         free_array_list(dev_list1,dev_num1);
  762.  
  763.         for(i=0; !dobreak() && i<dev_num2; i++)
  764.             printf("%s\n",dev_list2[i]);
  765.         free_array_list(dev_list2,dev_num2);
  766.  
  767.         break;
  768.     case 1:
  769.         for (i=1; i<ac; i++)
  770.             if (loadres(av[i]))
  771.                 printf("OK! %s is now resident\n", FilePart(av[i]));
  772.             else
  773.                 pError(av[i]);
  774.         break;
  775.     case 2:
  776.         for (i=1; i<ac; i++) {
  777.             Forbid();
  778.             if (seg=FindSegment(av[i],NULL,0L)) {
  779.                 if (RemSegment(seg)) {
  780.                     Permit();
  781.                     printf("Removed %s\n",av[i]);
  782.                 }
  783.                 else {
  784.                     Permit();
  785.                     ierror(av[i],ERROR_OBJECT_IN_USE);
  786.                 }
  787.             }
  788.             else {
  789.                 Permit();
  790.                 ierror(av[i],ERROR_OBJECT_NOT_FOUND);
  791.             }
  792.         }
  793.         break;
  794.     case 4:
  795.         for (i=1; i<ac; i++) {
  796.             if( !o_resident ) {
  797.                 /* AMK: OS20-SetVar replaces ARP-Setenv */
  798.                 SetVar(shellres,"1",-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  799.                 o_resident=1;
  800.             }
  801.             sprintf(buf,"res_%s",FilePart(av[i]));
  802.             /* AMK: OS20-SetVar replaces ARP-Setenv */
  803.             SetVar(buf,av[i],-1L,GVF_GLOBAL_ONLY|GVF_BINARY_VAR);
  804.         }
  805.         break;
  806.     default:
  807.         ierror(NULL,500);
  808.         break;
  809.     }
  810.     return 0;
  811. }
  812.  
  813. int
  814. loadres(char *s)
  815. {
  816.     BPTR seg;
  817.     BOOL okay = FALSE;
  818.  
  819.     if (seg=NewLoadSeg(s,NULL))
  820.         okay=AddSegment(FilePart(s),seg,1L);
  821.  
  822.     return (okay);
  823. }
  824.  
  825. extern BPTR redir_out, redir_in;
  826.  
  827. struct TagItem tags[]={
  828.     {SYS_Input,  0},
  829.     {SYS_Output, 0},
  830.     {SYS_Asynch, 1},
  831.     {TAG_DONE,   0} };
  832.  
  833. do_truerun(char *avline, int backflag)
  834. {
  835.     BPTR input, output;
  836.     char *args;
  837.     int err;
  838.  
  839.     if (backflag) {
  840.         input = Open("NIL:",MODE_NEWFILE);
  841.         output= Open("NIL:",MODE_NEWFILE);
  842.     } else {
  843.         input = redir_in ?redir_in : Open("NIL:"    , MODE_NEWFILE);
  844.         output= redir_out?redir_out: Open("CONSOLE:", MODE_NEWFILE);
  845.     }
  846.  
  847.     args=compile_av(av,1,ac,' ',1);
  848.  
  849.     tags[0].ti_Data= input;
  850.     tags[1].ti_Data= output;
  851.  
  852.     err=System( args, tags );
  853.  
  854.     if( err!=0 ) {
  855.         Close( tags[0].ti_Data );
  856.         Close( tags[1].ti_Data );
  857.         pError(av[1]);
  858.     }
  859.     free(args);
  860.  
  861.     return 0;
  862. }
  863.  
  864. #if 0
  865. extern BPTR redir_out, redir_in;
  866.  
  867. static struct ProcessControlBlock pcb={
  868.     4000,        /* pcb_StackSize    */
  869.     0,        /* pcb_Pri        */
  870.     };
  871. /* remaining fields are NULL */
  872.  
  873. do_truerun(char *avline, int backflag)
  874. {
  875.     char name[100], *args, buf[10];
  876.     int cli;
  877.  
  878.     args=next_word(next_word(avline));
  879.     if (backflag) {
  880.         pcb.pcb_Control= 0;
  881.         pcb.pcb_Input  = Open("NIL:",MODE_OLDFILE);
  882.         pcb.pcb_Output = Open("NIL:",MODE_OLDFILE);
  883.     } else {
  884.         pcb.pcb_Control= 0;
  885.         pcb.pcb_Input  = redir_in;
  886.         pcb.pcb_Output = redir_out;
  887.  
  888.     }
  889.  
  890.     if((cli=ASyncRun(av[1],args,&pcb))<0)
  891.         if (dofind(av[1], "", name,v_path))
  892.             cli=ASyncRun(name,args,&pcb);
  893.  
  894.     if( cli<0 && cli>=-11 ) {
  895.         if( redir_out ) extClose( redir_out );
  896.         if( redir_in  ) extClose( redir_in  );
  897.     }
  898.  
  899.     sprintf(buf,"%d",cli);
  900.     set_var(LEVEL_SET,"_newproc",buf);
  901.  
  902.     if( cli<0 ) {
  903.         ierror(av[1],205);
  904.         return 20;
  905.     }
  906.     return 0;
  907. }
  908. #endif
  909.  
  910. int
  911. exists( char *name )
  912. {
  913.     BPTR lock;
  914.     char *nam=FilePart(name);
  915.     int ret=0;
  916.  
  917.     Myprocess->pr_WindowPtr = (APTR)(-1);
  918.     if ( strlen(nam)<=MAXFILENAME && (lock=Lock(name,ACCESS_READ))) {
  919.         UnLock(lock);
  920.         ret=1;
  921.     }
  922.     Myprocess->pr_WindowPtr = (APTR) o_noreq;
  923.     return ret;
  924. }
  925.  
  926. int
  927. mounted( char *dev )
  928. {
  929.     struct DosList *dl;
  930.     ULONG flags = LDF_ALL|LDF_READ;
  931.     int gotcha = FALSE;
  932.     char devname[256];
  933.  
  934.     if (dl=LockDosList(flags)) {
  935.         while ((!gotcha) && (dl=NextDosEntry(dl,flags))) {
  936.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  937.             if (stricmp(devname,dev)==0)
  938.                 gotcha = TRUE;
  939.         }
  940.         UnLockDosList(flags);
  941.     }
  942.  
  943.     return (gotcha);
  944. }
  945.  
  946. #define HTYPELINE 16L
  947.  
  948. static int
  949. htype_a_file(long mask, char *s, char *path)
  950. {
  951.     BPTR fh;
  952.     long n, filesize=0;
  953.     UBYTE buf[HTYPELINE+1];
  954.     char out[80], *put;
  955.     int i, inter=IsInteractive(Output());
  956.     BOOL usestdin = (s==NULL);
  957.  
  958.     if (usestdin)
  959.         fh = Input();
  960.     else
  961.         fh = Open(s,MODE_OLDFILE);
  962.  
  963.     if (fh==NULL) { pError(s); return 20; }
  964.     prepscroll(0);
  965.     while ( (n=Read(fh,(char *)buf,HTYPELINE))>0 && !dobreak()) {
  966.         put=out;
  967.         put+=sprintf(put,"%06lx: ",filesize);
  968.         filesize+=n;
  969.         for (i=0; i<n; i++) {
  970.             put+=sprintf( put,(i&3) ? "%02x" : " %02x",buf[i]);
  971.             if ((buf[i]&127)<0x20) buf[i]='.';
  972.         }
  973.         for ( ; i<HTYPELINE; i++) {
  974.             put+=sprintf( put, (i&3) ? "  " : "   ");
  975.             buf[i]=' ';
  976.         }
  977.         buf[i]=0;
  978.         sprintf(put,"    %s",buf);
  979.         puts(out);
  980.         if( inter ) fflush(stdout);
  981.         quickscroll();
  982.     }
  983.     /* only close file if not standard input */
  984.     if (!usestdin)
  985.         Close(fh);
  986.     return 0;
  987. }
  988.  
  989. do_htype( void )
  990. {
  991.     if (ac<2)
  992.         htype_a_file(0, NULL, NULL);
  993.     else
  994.         all_args( htype_a_file, 0);
  995.     return 0;
  996. }
  997.  
  998. #define STACK_MIN_FREE 10000
  999. do_stack( void )
  1000. {
  1001.     long n;
  1002.  
  1003.     if (ac>1) {
  1004.         if (isnum(av[1])) {   /* AMK: IoErr() replaced by isnum() */
  1005.             n=atol(av[1]);
  1006.             if ( n < 1600 )
  1007.                 printf("Requested size too small\n");
  1008.             else if ( n > (AvailMem(MEMF_LARGEST)-STACK_MIN_FREE) )
  1009.                 printf("Requested size too large\n");
  1010.             else
  1011.             Mycli->cli_DefaultStack=(long)(n >> 2L);
  1012.         }
  1013.         else {
  1014.             ierror(av[1],511);   /* AMK: message if error */
  1015.             return 20;
  1016.         }
  1017.     }
  1018.     else {
  1019.         if (options&1)
  1020.             printf("%ld\n",(long)Mycli->cli_DefaultStack << 2L);
  1021.         else
  1022.             printf("current stack size is %ld bytes\n",
  1023.                     (long)Mycli->cli_DefaultStack << 2L);
  1024.     }
  1025.     return 0;
  1026. }
  1027.  
  1028. do_fault( void )
  1029. {
  1030.     PERROR *p;
  1031.     int i, n;
  1032.  
  1033.     for (i=1; i<ac; i++) {
  1034.         n=myatoi(av[i],0,32767);
  1035.         if (!atoierr) {
  1036.             for (p=Perror; p->errnum && p->errnum!=n; p++);
  1037.             if (p->errnum)
  1038.                 printf("Fault %d: %s\n",n,p->errstr);
  1039.             else
  1040.                 printf("Fault %d not recognized\n",n);
  1041.         }
  1042.     }
  1043.     return 0;
  1044. }
  1045.  
  1046. struct rpncommand {
  1047.     char *str;
  1048.     int parsin, parsout;
  1049.     };
  1050.  
  1051. static struct rpncommand rpn[]={
  1052.     "+",    2,    1,
  1053.     "-",    2,    1,
  1054.     "*",    2,    1,
  1055.     "/",    2,    1,
  1056.     "%",    2,    1,
  1057.     "&",    2,    1,
  1058.     "|",    2,    1,
  1059.     "~",    1,    1,
  1060.     ">",    2,    1,
  1061.     "<",    2,    1,
  1062.     "==",    2,    1,
  1063.     "!",    1,    1,
  1064.     "MAX",    2,    1,
  1065.     "MIN",    2,    1,
  1066.     "DUP",    1,    2,
  1067.     "DROP",    1,    0,
  1068.     "SWAP",    2,    2,
  1069.     "HELP",    0,    0,
  1070.     NULL,    0,    1,    /* this looks for a number */
  1071. };
  1072.  
  1073. static long stack[50];
  1074. static int sp;
  1075.  
  1076.  
  1077. eval_rpn( char **av, int ac, int flag )
  1078. {
  1079.     char *zero="Division by zero\n";
  1080.     struct rpncommand *temp;
  1081.     long n0, n1, t;
  1082.     int j, i=0, oldsp=sp;
  1083.  
  1084.     for (; i<ac; i++) {
  1085.         for (j=0; rpn[j].str && stricmp(rpn[j].str,av[i]); j++) ;
  1086.         n0=stack[sp-1];
  1087.         n1=stack[sp-2];
  1088.         sp -= (rpn[j].parsin);
  1089.         if (sp<0) { fprintf(stderr, "RPN: Empty stack\n"); goto error; }
  1090.         switch (j) {
  1091.           case 0:    n0 += n1;            break;
  1092.           case 1:    n0 = n1-n0;            break;
  1093.           case 2:    n0 *= n1;            break;
  1094.           case 3:    if(n0) n0=n1/n0; else fprintf(stderr,zero); break;
  1095.           case 4:    if(n0) n0=n1%n0; else fprintf(stderr,zero); break;
  1096.           case 5:    n0 &= n1;            break;
  1097.           case 6:    n0 |= n1;            break;
  1098.           case 7:    n0 =  ~n0    ;        break;
  1099.           case 8:    n0 = (n1 > n0);        break;
  1100.           case 9:    n0 = (n1 < n0);        break;
  1101.           case 10:    n0 = (n0 == n1);    break;
  1102.           case 11:    n0 = !n0;            break;
  1103.           case 12:    n0=n1>n0 ? n1 : n0;    break;
  1104.           case 13:    n0=n1<n0 ? n1 : n0;    break;
  1105.           case 14:    n1=n0;                break;
  1106.           case 15:    t=n0; n0=n1; n1=t;    break;
  1107.           case 16:                        break;
  1108.           case 17:    printf("In Commands Out\n");
  1109.             for (temp=rpn; temp->str; temp++)
  1110.                 printf(" %d %-10s%d\n",
  1111.                 temp->parsin,temp->str,temp->parsout);
  1112.             break;
  1113.           default:    n0=atol(av[i]);
  1114.                 if (!isnum(av[i])) {   /* AMK: IoErr() replaced by isnum() */
  1115.                     fprintf(stderr, "Bad RPN cmd: %s\n",av[i]);
  1116.                     goto error;
  1117.                 }
  1118.                 break;
  1119.           }
  1120.         stack[sp]=n0;
  1121.         stack[sp+1]=n1;
  1122.         sp += rpn[j].parsout;
  1123.     }
  1124.     if( flag && sp-1)
  1125.         fprintf( 
  1126.           stderr,
  1127.           "RPN: Stack not empty\n"
  1128.         );
  1129.  
  1130.     t=sp; sp=oldsp;
  1131.     if( flag )
  1132.         return stack[t-1]; /* return top value */
  1133.     else
  1134.         return t-sp;
  1135.  
  1136. error:
  1137.     sp=oldsp;
  1138.     return 0;
  1139. }
  1140.  
  1141.  
  1142. do_rpn(char *garbage,int ifflag) /* ifflag!=0 if called from if */
  1143. {
  1144.     int i=1;
  1145.     long t;
  1146.  
  1147.     t=eval_rpn( av+i, ac-i, ifflag );
  1148.     if (ifflag) return t;              /* called from if: return top value */
  1149.     for (i=sp+t-1;i>=sp;i--) printf("%ld\n", stack[i]);/* else print stack */
  1150.  
  1151.     return t ? 0 : 20;
  1152. }
  1153.  
  1154.  
  1155.  
  1156. void *DosAllocMem(long size)
  1157. {
  1158.     return( AllocVec(size,MEMF_CLEAR|MEMF_PUBLIC) );
  1159. }
  1160.  
  1161.  
  1162.  
  1163. void DosFreeMem(void *block)
  1164. {
  1165.     FreeVec(block);
  1166. }
  1167.  
  1168.  
  1169.  
  1170. /* do_rehash related stuff ... */
  1171.  
  1172. #define PATHHASH_RSRC "CSH-PathHash"
  1173. #define PATHHASH_SEMA "CSH-PathHash"
  1174.  
  1175. struct PathHashRsrc {
  1176.     struct Library phr_Lib;
  1177.     struct SignalSemaphore phr_Sema;
  1178.     long phr_entries;
  1179.     char *phr_data;
  1180. };
  1181.  
  1182.  
  1183.  
  1184. char *get_rehash_prog(char *last,char *progname)
  1185. {
  1186.     long i;
  1187.     char *filepart;
  1188.  
  1189.     if (last) {
  1190.         for(i=0; i<prghash_num && prghash_list[i]!=last; i++)
  1191.             ;
  1192.  
  1193.         for(++i; i<prghash_num; i++) {
  1194.             if (filepart=FilePart(prghash_list[i])) {
  1195.                 if (strnicmp(progname,filepart,strlen(progname))==0)
  1196.                     return( prghash_list[i] );
  1197.             }
  1198.         }
  1199.     }
  1200.  
  1201.     for(i=0; i<prghash_num; i++) {
  1202.         if (filepart=FilePart(prghash_list[i])) {
  1203.             if (strnicmp(progname,filepart,strlen(progname))==0)
  1204.                 return( prghash_list[i] );
  1205.         }
  1206.     }
  1207.  
  1208.     return( NULL );
  1209. }
  1210.  
  1211.  
  1212.  
  1213. void resolve_multiassign(char *ma,char **dev_list,long *dev_num)
  1214. {
  1215.     struct DosList *dl;
  1216.     struct AssignList *path;
  1217.     ULONG flags;
  1218.     char *colon;
  1219.     char fmt[256],devname[256];
  1220.  
  1221.     flags = LDF_ASSIGNS|LDF_READ;
  1222.     colon = strchr(ma,':');
  1223.  
  1224.     if (colon && (dl=LockDosList(flags))) {
  1225.         *colon = '\0';
  1226.         while (dl=NextDosEntry(dl,flags)) {
  1227.             BtoCStr(devname,dl->dol_Name,254L);  /* 256 - '\0' + ':' */
  1228.  
  1229.             if (stricmp(devname,ma)==0) {
  1230.  
  1231.                 if (dl->dol_Type == DLT_DIRECTORY) {
  1232.                     if(dl->dol_Lock) {
  1233.                         NameFromLock(dl->dol_Lock,fmt,255L);
  1234.                         if (*(colon+1))
  1235.                             AddPart(fmt,colon+1,255);
  1236.                         add_array_list(&dev_list,dev_num,fmt);
  1237.                     }
  1238.                     else
  1239.                         printf("Nonexisting lock (1) %s\n",devname);
  1240.  
  1241.                     if (path=dl->dol_misc.dol_assign.dol_List) {
  1242.                         for (; path; path=path->al_Next) {
  1243.                             if (dl->dol_Lock) {
  1244.                                 NameFromLock(path->al_Lock,fmt,255L);
  1245.                                 if (*(colon+1))
  1246.                                     AddPart(fmt,colon+1,255);
  1247.                                 add_array_list(&dev_list,dev_num,fmt);
  1248.                             }
  1249.                             else
  1250.                                 printf("Nonexisting lock (1) %s\n",devname);
  1251.                         }
  1252.                     }
  1253.                 }
  1254.             }
  1255.         }
  1256.         UnLockDosList(flags);
  1257.         *colon = ':';
  1258.     }
  1259. }
  1260.  
  1261.  
  1262.  
  1263. void remove_local_pathhash(void)
  1264. {
  1265.     free_array_list(prghash_list,prghash_num);
  1266.     prghash_list = NULL;
  1267.     prghash_num  = 0;
  1268. }
  1269.  
  1270.  
  1271.  
  1272. BOOL remove_global_pathhash(void)
  1273. {
  1274.     struct PathHashRsrc *rsrc;
  1275.     BOOL success = FALSE;
  1276.  
  1277.     Forbid();
  1278.     if (rsrc = OpenResource(PATHHASH_RSRC)) {
  1279.         if (rsrc->phr_Lib.lib_OpenCnt == 0) {
  1280.             RemResource(rsrc);
  1281.             RemSemaphore(&rsrc->phr_Sema);
  1282.             FreeVec(rsrc->phr_Sema.ss_Link.ln_Name);
  1283.             FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1284.             if (rsrc->phr_data) FreeVec(rsrc->phr_data);
  1285.             FreeVec(rsrc);
  1286.             success = TRUE;
  1287.         }
  1288.     }
  1289.     Permit();
  1290.  
  1291.     return(success);
  1292. }
  1293.  
  1294.  
  1295.  
  1296. void load_pathhash_from_mem(struct PathHashRsrc *rsrc)
  1297. {
  1298.     char *cp;
  1299.     long i;
  1300.  
  1301.     remove_local_pathhash();
  1302.  
  1303.     cp = rsrc->phr_data;
  1304.  
  1305.     for (i=rsrc->phr_entries; i>0; i--) {
  1306.         add_array_list(&prghash_list,&prghash_num,cp);
  1307.         cp += strlen(cp)+1;
  1308.     }
  1309. }
  1310.  
  1311.  
  1312.  
  1313. void save_pathhash_to_mem(struct PathHashRsrc *rsrc,long hashlen)
  1314. {
  1315.     char *new_data;
  1316.  
  1317.     if (new_data = AllocVec(hashlen,MEMF_PUBLIC|MEMF_CLEAR)) {
  1318.         long slen,i;
  1319.  
  1320.         /* free old path hash data */
  1321.         if (rsrc->phr_data) FreeVec(rsrc->phr_data);
  1322.  
  1323.         /* set new memory pointer */
  1324.         rsrc->phr_data = new_data;
  1325.  
  1326.         /* copy path hash data to memory */
  1327.         for(i=0; i<prghash_num; i++) {
  1328.             slen = strlen(prghash_list[i])+1;
  1329.             CopyMem(prghash_list[i],new_data,slen);
  1330.             new_data += slen;
  1331.         }
  1332.  
  1333.         /* set new number of entries */
  1334.         rsrc->phr_entries = prghash_num;
  1335.     }
  1336. }
  1337.  
  1338.  
  1339.  
  1340. do_rehash( void )
  1341. {
  1342.     /*
  1343.             (re-)build internal hash-list        (no option)
  1344.        -c : clear hash-list from memory          (options&1)
  1345.        -l : load hash-list from disk to memory   (options&2)
  1346.        -o : output hash-list from memory         (options&4)
  1347.        -s : save hash-list from memory to disk   (options&8)
  1348.        -g : free global hash-list                (options&16)
  1349.     */
  1350.     struct PathHashRsrc *rsrc;
  1351.     long i;
  1352.     char buf[256];
  1353.  
  1354.     if (options&1) {    /* clear hash-list */
  1355.  
  1356.         remove_local_pathhash();
  1357.     }
  1358.     else if (options&2) {    /* load hash-list */
  1359.         FILE *fp;
  1360.         char *lf,*fname;
  1361.         BOOL readin = FALSE;
  1362.  
  1363.         if (!(fname=get_var(LEVEL_SET,v_prghash))) {
  1364.             fprintf(stderr,"$_prghash unset\n");
  1365.             return 20;
  1366.         }
  1367.  
  1368.         Forbid();
  1369.         if (!(rsrc = OpenResource(PATHHASH_RSRC))) {
  1370.             if (rsrc=AllocVec(sizeof(struct PathHashRsrc),MEMF_PUBLIC|MEMF_CLEAR)) {
  1371.                 rsrc->phr_Lib.lib_Node.ln_Type = NT_RESOURCE;
  1372.                 rsrc->phr_Lib.lib_Node.ln_Pri  = 0;
  1373.                 if (rsrc->phr_Lib.lib_Node.ln_Name=AllocVec(strlen(PATHHASH_RSRC)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1374.                     strcpy(rsrc->phr_Lib.lib_Node.ln_Name,PATHHASH_RSRC);
  1375.                     if (rsrc->phr_Sema.ss_Link.ln_Name=AllocVec(strlen(PATHHASH_SEMA)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1376.                         strcpy(rsrc->phr_Sema.ss_Link.ln_Name,PATHHASH_SEMA);
  1377.                         rsrc->phr_Sema.ss_Link.ln_Pri = 0;
  1378.                         AddSemaphore(&rsrc->phr_Sema);
  1379.                         AddResource(rsrc);
  1380.                         readin = TRUE;
  1381.                     }
  1382.                     else {
  1383.                         FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1384.                         FreeVec(rsrc);
  1385.                     }
  1386.                 }
  1387.                 else {
  1388.                     FreeVec(rsrc);
  1389.                 }
  1390.             }
  1391.         }
  1392.         if (rsrc) {
  1393.             rsrc->phr_Lib.lib_OpenCnt++;
  1394.             if (readin)
  1395.                 ObtainSemaphore(&rsrc->phr_Sema);
  1396.             else
  1397.                 ObtainSemaphoreShared(&rsrc->phr_Sema);
  1398.         }
  1399.         Permit();
  1400.  
  1401.         if (!rsrc) {
  1402.             printf("csh: cannot create resource\n");
  1403.             return 10;
  1404.         }
  1405.  
  1406.         /* clear old list -- if any */
  1407.         remove_local_pathhash();
  1408.  
  1409.         if (readin) {
  1410.             long hashlen = 0;
  1411.             if (fp=fopen(fname,"r")) {
  1412.                 while (fgets(buf,255,fp)) {
  1413.                     if (lf=strchr(buf,'\n')) {
  1414.                         *lf = '\0';
  1415.                     }
  1416.                     add_array_list(&prghash_list,&prghash_num,buf);
  1417.                     hashlen += strlen(buf)+1;
  1418.                 }
  1419.                 fclose(fp);
  1420.             }
  1421.             else
  1422.                 pError(fname);
  1423.             save_pathhash_to_mem(rsrc,hashlen);
  1424.         }
  1425.         else {
  1426.             load_pathhash_from_mem(rsrc);
  1427.         }
  1428.  
  1429.         Forbid();
  1430.         ReleaseSemaphore(&rsrc->phr_Sema);
  1431.         rsrc->phr_Lib.lib_OpenCnt--;
  1432.         Permit();
  1433.     }
  1434.     else if (options&4) {    /* output hash-list */
  1435.  
  1436.         for(i=0; !dobreak() && i<prghash_num; i++)
  1437.             printf("%s\n",prghash_list[i]);
  1438.     }
  1439.     else if (options&8) {    /* save hash-list */
  1440.         FILE *fp;
  1441.         char *fname;
  1442.  
  1443.         if (!(fname=get_var(LEVEL_SET,v_prghash))) {
  1444.             fprintf(stderr,"$_prghash unset\n");
  1445.             return 20;
  1446.         }
  1447.  
  1448.         if (fp=fopen(fname,"w")) {
  1449.             for(i=0; i<prghash_num; i++)
  1450.                 fprintf(fp,"%s\n",prghash_list[i]);
  1451.             fclose(fp);
  1452.         }
  1453.         else
  1454.             pError(fname);
  1455.  
  1456.     }
  1457.     else if (options&16) {    /* free global hash-list */
  1458.  
  1459.         if (!remove_global_pathhash())
  1460.             printf("csh: cannot clear, currently in use or does not exist\n");
  1461.     }
  1462.     else {
  1463.         BPTR lock;
  1464.         struct PathList *pl;
  1465.         struct FileInfoBlock *fib;
  1466.         char **path_list = NULL;
  1467.         long path_num = 0;
  1468.         long hashlen = 0;
  1469.         long slen;
  1470.  
  1471.         /* clear old list -- if any */
  1472.         remove_local_pathhash();
  1473.  
  1474.         Forbid();
  1475.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1476.         while (pl) {
  1477.             if (pl->pl_PathLock) {
  1478.                 NameFromLock(pl->pl_PathLock,buf,255L);
  1479.                 add_array_list(&path_list,&path_num,buf);
  1480.             }
  1481.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1482.         }
  1483.         Permit();
  1484.  
  1485.         resolve_multiassign("C:",path_list,&path_num);
  1486.  
  1487.         if (fib=AllocVec(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) {
  1488.             for(i=0; !dobreak() && i<path_num; i++) {
  1489.                 if (lock=Lock(path_list[i],SHARED_LOCK)) {
  1490.                     if (Examine(lock,fib)) {
  1491.                         while (!dobreak() && ExNext(lock,fib)) {
  1492.                             if (fib->fib_DirEntryType<0) {
  1493.                                 slen = strlen(fib->fib_FileName);
  1494.                                 if (slen<5 || stricmp(fib->fib_FileName+slen-5,".info")!=0) {
  1495.                                     strcpy(buf,path_list[i]);
  1496.                                     if (AddPart(buf,fib->fib_FileName,255)) {
  1497.                                         add_array_list(&prghash_list,&prghash_num,buf);
  1498.                                         hashlen += strlen(buf)+1;
  1499.                                     }
  1500.                                     else {
  1501.                                         printf("path too long: %s -> %s\n",path_list[i],fib->fib_FileName);
  1502.                                     }
  1503.                                 }
  1504.                             }
  1505.                         }
  1506.                     }
  1507.                     UnLock(lock);
  1508.                 }
  1509.             }
  1510.             FreeVec(fib);
  1511.         }
  1512.  
  1513.         free_array_list(path_list,path_num);
  1514.  
  1515.         Forbid();
  1516.         if (!(rsrc = OpenResource(PATHHASH_RSRC))) {
  1517.             if (rsrc=AllocVec(sizeof(struct PathHashRsrc),MEMF_PUBLIC|MEMF_CLEAR)) {
  1518.                 rsrc->phr_Lib.lib_Node.ln_Type = NT_RESOURCE;
  1519.                 rsrc->phr_Lib.lib_Node.ln_Pri  = 0;
  1520.                 if (rsrc->phr_Lib.lib_Node.ln_Name=AllocVec(strlen(PATHHASH_RSRC)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1521.                     strcpy(rsrc->phr_Lib.lib_Node.ln_Name,PATHHASH_RSRC);
  1522.                     if (rsrc->phr_Sema.ss_Link.ln_Name=AllocVec(strlen(PATHHASH_SEMA)+1,MEMF_PUBLIC|MEMF_CLEAR)) {
  1523.                         strcpy(rsrc->phr_Sema.ss_Link.ln_Name,PATHHASH_SEMA);
  1524.                         rsrc->phr_Sema.ss_Link.ln_Pri = 0;
  1525.                         AddSemaphore(&rsrc->phr_Sema);
  1526.                         AddResource(rsrc);
  1527.                     }
  1528.                     else {
  1529.                         FreeVec(rsrc->phr_Lib.lib_Node.ln_Name);
  1530.                         FreeVec(rsrc);
  1531.                     }
  1532.                 }
  1533.                 else {
  1534.                     FreeVec(rsrc);
  1535.                 }
  1536.             }
  1537.         }
  1538.         if (rsrc) {
  1539.             rsrc->phr_Lib.lib_OpenCnt++;
  1540.             ObtainSemaphore(&rsrc->phr_Sema);
  1541.         }
  1542.         Permit();
  1543.  
  1544.         if (!rsrc) {
  1545.             printf("csh: cannot create resource\n");
  1546.             return 10;
  1547.         }
  1548.  
  1549.         save_pathhash_to_mem(rsrc,hashlen);
  1550.  
  1551.         Forbid();
  1552.         ReleaseSemaphore(&rsrc->phr_Sema);
  1553.         rsrc->phr_Lib.lib_OpenCnt--;
  1554.         Permit();
  1555.     }
  1556.  
  1557.     return 0;
  1558. }
  1559.  
  1560.  
  1561.  
  1562. do_path( void )
  1563. {
  1564.     struct Process *proc;
  1565.     BPTR lock,dup_lock;
  1566.     long mycli,clinum,mincli,maxcli;
  1567.     struct PathList *pl,*new_pl,*old,*last;
  1568.     char buf[256];
  1569.     int i;
  1570.  
  1571.     if ( options&1 ) {
  1572.         long noram = 0;
  1573.         Forbid();
  1574.         mincli = 1;
  1575.         maxcli = MaxCli();
  1576.         mycli  = Myprocess->pr_TaskNum;
  1577.         if (!(options&2))
  1578.             mincli = maxcli = mycli;
  1579.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1580.             if (proc=FindCliProc(clinum)) {
  1581.                 pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1582.                 while (pl) {
  1583.                     if (pl->pl_PathLock) {
  1584.                         UnLock(pl->pl_PathLock);
  1585.                     }
  1586.                     old = pl;
  1587.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1588.                     if (TypeOfMem(old) != 0)
  1589.                         DosFreeMem( old );
  1590.                     else
  1591.                         ++noram;
  1592.                 }
  1593.                 CLI(proc)->cli_CommandDir=NULL;
  1594.             }
  1595.         }
  1596.         Permit();
  1597.         fprintf(stderr,"%ld structure%s (%ld bytes) not freed, memory isn't in known RAM\n",
  1598.                 noram,
  1599.                 (noram>1) ? "s":"",
  1600.                 noram*sizeof(struct PathList));
  1601.     } else if( ac==1 ) {
  1602.         char **dev_list=NULL;
  1603.         long dev_num=0,i;
  1604.         puts("Current dir");
  1605.         Forbid();
  1606.         pl = (struct PathList *)BADDR(Mycli->cli_CommandDir);
  1607.         while (pl) {
  1608.             if (pl->pl_PathLock) {
  1609.                 NameFromLock(pl->pl_PathLock,buf,255L);
  1610.                 add_array_list(&dev_list,&dev_num,buf);
  1611.             }
  1612.             pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1613.         }
  1614.         Permit();
  1615.  
  1616.         for(i=0; !dobreak() && i<dev_num; i++)
  1617.             printf("%s\n",dev_list[i]);
  1618.         free_array_list(dev_list,dev_num);
  1619.  
  1620.         if (!dobreak())
  1621.             puts("C:");
  1622.         return 0;
  1623.     }
  1624.     for( i=1; i<ac; i++ ) {
  1625.         if( !(lock=Lock(av[i],ACCESS_READ)) ) {
  1626.             ierror(av[i],205);
  1627.             continue;
  1628.         }
  1629.         if( !isdir(av[i])) {
  1630.             ierror(av[i],212);
  1631.             UnLock(lock);
  1632.             continue;
  1633.         }
  1634.         Forbid();
  1635.         mincli = 1;
  1636.         maxcli = MaxCli();
  1637.         mycli  = Myprocess->pr_TaskNum;
  1638.         if (!(options&2))
  1639.             mincli = maxcli = mycli;
  1640.         for (clinum = mincli; clinum<=maxcli; clinum++) {
  1641.             if (proc=FindCliProc(clinum)) {
  1642.                 if (options&2)
  1643.                     dup_lock = DupLock(lock);
  1644.                 else
  1645.                     dup_lock = lock;
  1646.                 last = pl = (struct PathList *)BADDR(CLI(proc)->cli_CommandDir);
  1647.                 while (pl && dup_lock) {
  1648.                     last = pl;
  1649.                     if (pl->pl_PathLock) {
  1650.                         if (SameLock(pl->pl_PathLock,dup_lock)==LOCK_SAME) {
  1651.                             UnLock(dup_lock);
  1652.                             dup_lock=NULL;
  1653.                         }
  1654.                     }
  1655.                     pl = (struct PathList *)BADDR(pl->pl_NextPath);
  1656.                 }
  1657.                 if (dup_lock) {
  1658.                     if (new_pl=DosAllocMem( sizeof(struct PathList) )) {
  1659.                         new_pl->pl_NextPath = NULL;
  1660.                         new_pl->pl_PathLock = dup_lock;
  1661.                         if (last)
  1662.                             last->pl_NextPath = MKBADDR(new_pl);
  1663.                         else
  1664.                             CLI(proc)->cli_CommandDir = MKBADDR(new_pl);
  1665.                     }
  1666.                     else
  1667.                         UnLock(dup_lock);
  1668.                 }
  1669.             }
  1670.         }
  1671.         Permit();
  1672.         if (options&2)
  1673.             UnLock(lock);
  1674.     }
  1675.     return 0;
  1676. }
  1677.  
  1678. do_pri( void )
  1679. {
  1680.     int t, pri;
  1681.     struct Process *proc;
  1682.  
  1683.     t=(LONG)MaxCli();
  1684.     t=myatoi(av[1],0,t); if (atoierr) return 20;
  1685.     pri=myatoi(av[2],-128,127); if (atoierr) return 20;
  1686.     Forbid();
  1687.     proc=(t==0 ? Myprocess : FindCliProc((LONG)t));
  1688.     if (proc==NULL) fprintf(stderr, "process not found\n");
  1689.     else SetTaskPri((struct Task *)proc, (long)pri);
  1690.     Permit();
  1691.     return 0;
  1692. }
  1693.  
  1694. do_strleft( void )
  1695. {
  1696.     int n;
  1697.  
  1698.     n=posatoi(av[3]); if (atoierr) return 20;
  1699.     set_var_n(LEVEL_SET, av[1], av[2], n);
  1700.     return 0;
  1701. }
  1702.  
  1703. do_strright( void )
  1704. {
  1705.     int n, len=strlen(av[2]);
  1706.  
  1707.     n=posatoi(av[3]); if (atoierr) return 20;
  1708.     if( n>len ) n=len;
  1709.     set_var(LEVEL_SET, av[1], av[2]+len-n );
  1710.     return 0;
  1711. }
  1712.  
  1713. do_strmid( void )
  1714. {
  1715.     int n1, n2=999999, len=strlen(av[2]);
  1716.  
  1717.     n1=myatoi(av[3],1,999999)-1; if (atoierr) return 20;
  1718.     if (n1>len) n1=len;
  1719.     if (ac>4) {
  1720.         n2=posatoi(av[4]); if (atoierr) return 20;
  1721.     }
  1722.     set_var_n(LEVEL_SET, av[1], av[2]+n1, n2);
  1723.     return 0;
  1724. }
  1725.  
  1726. do_strlen( void )
  1727. {
  1728.     char buf[16];
  1729.  
  1730.     sprintf(buf,"%d",strlen(av[2]));
  1731.     set_var(LEVEL_SET, av[1], buf);
  1732.     return 0;
  1733. }
  1734.  
  1735. int atoierr;
  1736.  
  1737. myatoi(char *s,int mmin,int mmax)
  1738. {
  1739.     int n;
  1740.  
  1741.     atoierr=0;   /* GMD: initialise external flag! */
  1742.     n=atol(s);
  1743.  
  1744.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1745.         atoierr=1;
  1746.         ierror(s,511);
  1747.     }
  1748.     else if (n<mmin || n>mmax) {
  1749.         /*fprintf( stderr, "%s(%d) not in (%d,%d)\n",s,n,mmin,mmax );*/
  1750.         fprintf( stderr, "%s not in (%d,%d)\n",s,mmin,mmax );
  1751.         atoierr=1; n=mmin;
  1752.     }
  1753.     return n;
  1754. }
  1755.  
  1756. unlatoi(char *s)
  1757. {
  1758.     int n=atol(s);
  1759.     atoierr=0;
  1760.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1761.         atoierr=1;
  1762.         ierror(s,511);
  1763.         n=0;
  1764.     }
  1765.     return n;
  1766. }
  1767.  
  1768. posatoi(char *s)
  1769. {
  1770.     int n=atol(s);
  1771.     atoierr=0;
  1772.     if (!isnum(s)) {   /* AMK: IoErr() replaced by isnum() */
  1773.         atoierr=1;
  1774.         ierror(s,511);
  1775.         n=0;
  1776.     }
  1777.     else if (n<0 )
  1778.         atoierr=1, n=0, fprintf( stderr, "%s must be positive\n",s );
  1779.     return n;
  1780. }
  1781.  
  1782.  
  1783. do_fltlower( void )
  1784. {
  1785.     return line_filter( strlwr );
  1786. }
  1787.  
  1788. do_fltupper( void )
  1789. {
  1790.     return line_filter( strupr );
  1791. }
  1792.  
  1793. #if 0
  1794. char *
  1795. stripcr( char *get )
  1796. {
  1797.     char *old=get, *put;
  1798.  
  1799.     for( put=get; *get; get++ )
  1800.         if( *get!=13 )
  1801.             *put++=*get;
  1802.     *put++=0;
  1803.     return old;
  1804. }
  1805.  
  1806. do_fltstripcr( void )
  1807. {
  1808.     return line_filter( stripcr );
  1809. }
  1810. #endif
  1811.  
  1812. static int
  1813. line_filter( char *(*func)( char * ) )
  1814. {
  1815.     char buf[256];
  1816.  
  1817.     while (!CHECKBREAK() && myfgets(buf,stdin))
  1818.         puts((*func)(buf));
  1819.     return 0;
  1820. }
  1821.  
  1822. int
  1823. do_linecnt( void )
  1824. {
  1825.     int count=0;
  1826.     char buf[256];
  1827.  
  1828.     while (!CHECKBREAK() && fgets(buf,255,stdin)) ++count;
  1829.     printf("%d lines\n",count);
  1830.     return 0;
  1831. }
  1832.  
  1833. int
  1834. do_uniq( void )
  1835. {
  1836.     int firstline=1;
  1837.     char buf[256], oldbuf[256];
  1838.  
  1839.     while (!CHECKBREAK() && myfgets(buf,stdin)) {
  1840.         if ( firstline || strcmp(buf, oldbuf)) {
  1841.             strcpy(oldbuf, buf);
  1842.             puts(buf);
  1843.         }
  1844.         firstline=0;
  1845.     }
  1846.     return 0;
  1847. }
  1848.  
  1849.  
  1850. #define RXFB_RESULT  17
  1851. #define RXCOMM    0x01000000
  1852.  
  1853. static struct rexxmsg {
  1854.     struct Message rm_Node;             /* EXEC message structure        */
  1855.     APTR     rm_TaskBlock;              /* global structure (private)    */
  1856.     APTR     rm_LibBase;                /* library base (private)        */
  1857.     LONG     rm_Action;                 /* command (action) code         */
  1858.     LONG     rm_Result1;                /* primary result (return code)  */
  1859.     LONG     rm_Result2;                /* secondary result              */
  1860.     STRPTR   rm_Args[16];               /* argument block (ARG0-ARG15)   */
  1861.  
  1862.     struct MsgPort *rm_PassPort;        /* forwarding port               */
  1863.     STRPTR   rm_CommAddr;               /* host address (port name)      */
  1864.     STRPTR   rm_FileExt;                /* file extension                */
  1865.     LONG     rm_Stdin;                  /* input stream (filehandle)     */
  1866.     LONG     rm_Stdout;                 /* output stream (filehandle)    */
  1867.     LONG     rm_avail;                  /* future expansion              */
  1868. } mymsg;                                /* size: 128 bytes               */
  1869.  
  1870.  
  1871. do_rxsend( char *avline )
  1872. {
  1873.     int i, ret=0;
  1874.     long result;
  1875.     struct MsgPort *port, *reply;
  1876.     long len;
  1877.     char buf[20], *resptr;
  1878.  
  1879.     if (!(port = (struct MsgPort *)FindPort(av[1])))
  1880.         { fprintf(stderr, "No port %s!\n", av[1]); return 20; }
  1881.     mymsg.rm_Node.mn_Node.ln_Type = NT_MESSAGE;
  1882.     mymsg.rm_Node.mn_Length = sizeof(struct rexxmsg);
  1883.     mymsg.rm_Action = RXCOMM | (options&1 ? 1L << RXFB_RESULT : 0);
  1884.     if (!(reply = CreateMsgPort())) {
  1885.         fprintf(stderr, "No reply port\n");
  1886.         return 20;
  1887.     }
  1888.     mymsg.rm_Node.mn_ReplyPort = reply;
  1889.  
  1890.     if( options&2 )
  1891.         av[2]=compile_av( av,2,ac,' ',0), ac=3;
  1892.     for ( i=2; i<ac; i++) {
  1893.         mymsg.rm_Args[0] = av[i];
  1894.         mymsg.rm_Result2 = 0;        /* clear out the last result. */
  1895.         PutMsg(port, &mymsg.rm_Node);
  1896.  
  1897.         Wait( 1<<reply->mp_SigBit | SIGBREAKF_CTRL_C );
  1898.  
  1899.         if( CHECKBREAK() ) {
  1900.             ret=5;
  1901.             break;
  1902.         }
  1903.  
  1904.         if (options&1) {
  1905.             if( (result=mymsg.rm_Result2)<1000000 ) { /* like AREXX */
  1906.                 sprintf(buf,"%d",result);              
  1907.                 set_var(LEVEL_SET,v_result,buf);
  1908.             } else {
  1909.                 resptr=(char *)(result-4);
  1910.                 len=*(long *)resptr;
  1911.                 memmove(resptr,resptr+4,len);  /* Null terminate */
  1912.                 resptr[len]=0;      
  1913.                 set_var(LEVEL_SET,v_result,resptr);
  1914.                 FreeMem(resptr, len+4 );
  1915.             }
  1916.         } else 
  1917.             unset_var( LEVEL_SET, v_result );
  1918.     }
  1919.     if( options&2 )
  1920.         free( av[2] );
  1921.  
  1922.     if (reply) DeleteMsgPort(reply);
  1923.     return ret;
  1924. }
  1925.  
  1926. static char *rxreturn;
  1927.  
  1928. do_rxrec( void )
  1929. {
  1930.     struct MsgPort *port;
  1931.     struct rexxmsg *msg;
  1932.     char *portname, *str;
  1933.  
  1934.     if (ac > 1)
  1935.         portname=av[1];
  1936.     else
  1937.         portname="rexx_csh";
  1938.  
  1939.     if (!(port=CreateMsgPort())) {
  1940.         fprintf(stderr, "Can't have MsgPort %s\n", portname);
  1941.         return 20;
  1942.     }
  1943.     port->mp_Node.ln_Name = portname;
  1944.     port->mp_Node.ln_Pri  = 0;
  1945.     AddPort(port);
  1946.     for (;;) {
  1947.         WaitPort(port);
  1948.         while (msg=(struct rexxmsg *)GetMsg(port)) {
  1949.             if ( ! stricmp(msg->rm_Args[0], "bye")) {
  1950.                 ReplyMsg((struct Message *)msg);
  1951.                 RemPort(port);
  1952.                 DeleteMsgPort(port);
  1953.                 return 0;
  1954.             }
  1955.             rxreturn=NULL;
  1956.             exec_command(msg->rm_Args[0]);
  1957.             if (msg->rm_Action & (1L << RXFB_RESULT)) {
  1958.                 if( rxreturn ) {
  1959.                     str= SAllocMem( strlen( rxreturn )+5 , 0 );
  1960.                     *(long *)str=strlen( rxreturn );
  1961.                     strcpy( str+4, rxreturn );
  1962.                     msg->rm_Result2=(long)str;
  1963.                 } else {
  1964.                     str = get_var(LEVEL_SET, v_lasterr);
  1965.                     msg->rm_Result2=(str) ? atoi(str) : 20;
  1966.                 }
  1967.             }
  1968.             ReplyMsg((struct Message *)msg);
  1969.         }
  1970.     }
  1971. }
  1972.  
  1973. int
  1974. do_waitport( void )
  1975. {
  1976.     int count=4*10;
  1977.     struct MsgPort *port=NULL;
  1978.  
  1979.     if( ac==3 ) 
  1980.         { count=2*myatoi(av[2],0, 32000); if( atoierr ) return 20; }
  1981.  
  1982.     while( --count>=0 && !(port=FindPort(av[1])) && !dobreak() )
  1983.         Delay(12);
  1984.  
  1985.     return port ? 0 : 20;
  1986. }
  1987.  
  1988. int
  1989. do_rxreturn( void )
  1990. {
  1991.     rxreturn=compile_av( av, 1, ac, ' ', 1 );
  1992.     return 0;
  1993. }
  1994.  
  1995. do_ascii( void )
  1996. {
  1997.     int x=1, y, c, c1, t;
  1998.     char *fmt1=" %3d %c%c |", *fmt2=" %4d";
  1999.  
  2000.     if( options&1 ) fmt1=" %3o %c%c |", fmt2="%4o";
  2001.     if( options&2 ) fmt1=" %3x %c%c |", fmt2="%4x";
  2002.     if( ac==x )
  2003.         for( y=0; y<32 && !dobreak(); y++ ) {
  2004.             printf("|");
  2005.             for( x=0; x<8; x++ ) {
  2006.                 c1=c=y+32*x; t=' ';
  2007.                 if( c<32 ) t='^', c1+=64;
  2008.                 printf(fmt1,c, t, c1<128 || c1>=160?c1:'.');
  2009.             }
  2010.             printf("\n");
  2011.         }
  2012.     else 
  2013.         for( ; x<ac && !dobreak(); x++ ) {
  2014.             for( y=0; y<strlen(av[x]); y++ )
  2015.                 printf(fmt2,av[x][y]);
  2016.             printf("\n");
  2017.         }
  2018.     return 0;
  2019. }
  2020.  
  2021. void
  2022. appendslash( char *path )
  2023. {
  2024.     int c;
  2025.  
  2026.     if( (c=path[strlen(path)-1]) !='/' && c!=':' )
  2027.         strcat(path,"/");
  2028. }
  2029.  
  2030. static void
  2031. whereis( char *path, char *file )
  2032. {
  2033.     char **eav, buf[100];
  2034.     int  eac, j;
  2035.  
  2036.     buf[0]=0;
  2037.     if( path ) {
  2038.         strcpy(buf,path);
  2039.         appendslash(buf);
  2040.     }
  2041.     strcat(buf,".../");
  2042.     strcat(buf,file);
  2043.     if( !index( file, '*' ) && !index( file, '?') )
  2044.         strcat(buf,"*");
  2045.     if(eav=expand(buf,&eac)) {
  2046.         for( j=0; j<eac && !dobreak(); j++ )
  2047.             printf("%s\n",eav[j]);
  2048.         free_expand(eav);
  2049.     }
  2050. }
  2051.  
  2052. do_whereis( void )
  2053. {
  2054.     char buf[200], *prev, *devs;
  2055.     int i;
  2056.  
  2057.     if( index( av[1],':') || index( av[1],'/' ) )
  2058.         { fprintf(stderr,"No paths please\n"); return 20; };
  2059.  
  2060.     if( options&1 ) {
  2061.         Myprocess->pr_WindowPtr = (APTR)(-1);
  2062.         get_drives( devs=buf );
  2063.         do {
  2064.             prev=devs; devs=index(devs,0xA0);
  2065.             if( devs ) *devs++=0; 
  2066.             whereis( prev, av[1] );
  2067.         } while( devs );
  2068.         Myprocess->pr_WindowPtr = (APTR) o_noreq;
  2069.     } else if( ac==2 ) {
  2070.         whereis( NULL, av[1] );
  2071.     } else {
  2072.         for( i=2; i<ac; i++ ) {
  2073.             strcpy(buf,av[i]);
  2074.             appendslash( buf );
  2075.             whereis( buf, av[1] );
  2076.         }
  2077.     }
  2078.     return 0;
  2079. }
  2080.  
  2081. do_usage( void )
  2082. {
  2083.     int i;
  2084.  
  2085.     if( ac==1 ) {
  2086.         printf("Usage: usage [command...command]\n");
  2087.         printf("[ ]=option   [ | ]=choice   { }=repetition   name...name=1 or more names\n");
  2088.     } else
  2089.         for( i=1; i<ac; i++ )
  2090.             show_usage( av[i] );
  2091.     return 0;
  2092. }
  2093.  
  2094.  
  2095.  
  2096. /* these defines are new in OS 3.x */
  2097. #ifndef WA_NewLookMenus
  2098. #define WA_NewLookMenus (WA_Dummy + 0x30)
  2099. #endif
  2100. #ifndef GTMN_NewLookMenus
  2101. #define GTMN_NewLookMenus GT_TagBase+67
  2102. #endif
  2103. #ifndef WFLG_NEWLOOKMENUS
  2104. #define WFLG_NEWLOOKMENUS 0x00200000
  2105. #endif
  2106.  
  2107.  
  2108.  
  2109. static struct NewMenu *NewMenus = NULL;
  2110. static int AnzMenus = 0, AnzItems = 1;
  2111. static APTR *visualInfo = NULL;
  2112. static struct Menu *menuStrip = NULL;
  2113. static char *fontName = NULL;
  2114. static struct TextAttr textAttr;
  2115. static struct TextFont *textFont = NULL;
  2116.  
  2117. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  2118.  
  2119. do_menu( void )
  2120. {
  2121.     if( o_nowindow )
  2122.         return 5;
  2123.  
  2124.     if( options&1 )
  2125.         remove_menu();
  2126.  
  2127.     if( ac==2 )
  2128.         show_usage( NULL );
  2129.     else if( AnzMenus<MAXMENUS && ac!=1)
  2130.         install_menu( av+1, ac-1 );
  2131.  
  2132.     set_menu();
  2133.     return 0;
  2134. }
  2135.  
  2136. static void
  2137. install_menu( char *mav[], int mac )
  2138. {
  2139.     char *p, *com;
  2140.     long msize;
  2141.     struct NewMenu *new_NewMenus;
  2142.     int i;
  2143.  
  2144.     if (o_nowindow || !Win)
  2145.         return;
  2146.  
  2147.     /* mac holds number of items, including title which counts as item */
  2148.  
  2149.     if (mac>MAXMENUITEMS)
  2150.         mac=MAXMENUITEMS;
  2151.  
  2152.     ClearMenuStrip( Win );
  2153.     if (menuStrip) FreeMenus(menuStrip);
  2154.     if (visualInfo) FreeVisualInfo(visualInfo);
  2155.     Delay(3);
  2156.  
  2157.     msize = sizeof(struct NewMenu) * (mac+1 + AnzItems-1);    /* one extra 'end' item */
  2158.     new_NewMenus = salloc(msize);
  2159.     memset(new_NewMenus,0,msize);
  2160.     if (NewMenus) {
  2161.         memcpy(new_NewMenus,NewMenus,sizeof(struct NewMenu)*(AnzItems-1));
  2162.         free(NewMenus);
  2163.     }
  2164.     else {
  2165.         int i,j;
  2166.         for (i=0; i<MAXMENUS; i++)
  2167.             for (j=0; j<MAXMENUITEMS; j++)
  2168.                 MenuCommand[i][j] = NULL;
  2169.     }
  2170.     NewMenus = new_NewMenus;
  2171.  
  2172.     NewMenus[AnzItems-1].nm_Type  = NM_TITLE;
  2173.     NewMenus[AnzItems-1].nm_Label = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  2174.  
  2175.     for( i=1; i<mac; i++) {
  2176.         com=NULL;
  2177.         if( p=index(mav[i],',')) {
  2178.             *p=0; com=++p;
  2179.             if( p=index(com,',')) {
  2180.                 *p=0;
  2181.                 NewMenus[AnzItems].nm_CommKey = strdup(++p);
  2182.             }
  2183.         }
  2184.  
  2185.         if( !com || !*com) {
  2186.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2187.             MenuCommand[AnzMenus][i-1]=com;
  2188.             com+=strlen(com);
  2189.             *com++=13;
  2190.             *com=0;
  2191.         } else {
  2192.             MenuCommand[AnzMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  2193.         }
  2194.  
  2195.         NewMenus[AnzItems].nm_Type  = NM_ITEM;
  2196.         NewMenus[AnzItems].nm_Label = strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2197.  
  2198.         AnzItems++;
  2199.     }
  2200.  
  2201.     AnzMenus++;
  2202.     NewMenus[AnzItems++].nm_Type = NM_END;
  2203.  
  2204.     if (!(visualInfo=GetVisualInfo(Win->WScreen,TAG_END))) {
  2205.         printf("no visual info\n");
  2206.         free(NewMenus);
  2207.     }
  2208.  
  2209.     if (!(menuStrip=CreateMenus(NewMenus,TAG_END))) {
  2210.         printf("no create menus\n");
  2211.         FreeVisualInfo(visualInfo);
  2212.         free(NewMenus);
  2213.     }
  2214.  
  2215.     /* do we want a monospaced (non-proportional) font? */
  2216.     if (options&2 && !textFont && AnzMenus<=1) {
  2217.         Forbid();
  2218.         if (GfxBase->DefaultFont) {
  2219.             textAttr.ta_Name = fontName = strdup(GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name);
  2220.             textAttr.ta_YSize = GfxBase->DefaultFont->tf_YSize;
  2221.         }
  2222.         else {
  2223.             textAttr.ta_Name  = "topaz.font";
  2224.             textAttr.ta_YSize = 8;
  2225.         }
  2226.         Permit();
  2227.         textAttr.ta_Style = FS_NORMAL;
  2228.         textAttr.ta_Flags = 0;
  2229.         if (textAttr.ta_Name)
  2230.             textFont = OpenDiskFont(&textAttr);
  2231.     }
  2232.  
  2233. /*
  2234.     if (!LayoutMenus(menuStrip,visualInfo,
  2235.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  2236.                 TAG_END))
  2237.     {
  2238. */
  2239.     if (!LayoutMenus(menuStrip,visualInfo,
  2240.                 Win->Flags&WFLG_NEWLOOKMENUS ? GTMN_NewLookMenus : TAG_IGNORE, TRUE,
  2241.                 textFont==NULL ? TAG_IGNORE : GTMN_TextAttr, &textAttr,
  2242.                 TAG_END))
  2243.     {
  2244.  
  2245.         printf("no layout menus\n");
  2246.         FreeMenus(menuStrip);
  2247.         FreeVisualInfo(visualInfo);
  2248.         free(NewMenus);
  2249.     }
  2250.  
  2251.     return;
  2252. }
  2253.  
  2254. void remove_menu()
  2255. {
  2256.     if (AnzMenus>0) {
  2257.         struct NewMenu *nm;
  2258.         int i,j;
  2259.  
  2260.         for (i=0; i<MAXMENUS; i++) {
  2261.             for (j=0 ;j<MAXMENUITEMS; j++)
  2262.                 if (MenuCommand[i][j]) {
  2263.                     free(MenuCommand[i][j]);
  2264.                     MenuCommand[i][j] = NULL;
  2265.                 }
  2266.         }
  2267.  
  2268.         for (nm=NewMenus; nm->nm_Type!=NM_END; nm++) {
  2269.             if (nm->nm_Label) {
  2270.                 free(nm->nm_Label);
  2271.                 nm->nm_Label = NULL;
  2272.             }
  2273.             if (nm->nm_CommKey) {
  2274.                 free(nm->nm_CommKey);
  2275.                 nm->nm_CommKey = NULL;
  2276.             }
  2277.         }
  2278.  
  2279.         AnzMenus=0;
  2280.         set_menu();
  2281.     }
  2282. }
  2283.  
  2284. void set_menu()
  2285. {
  2286.     if (o_nowindow || !Win)
  2287.         return;
  2288.  
  2289.     if (AnzMenus>0)
  2290.         SetMenuStrip(Win,menuStrip);
  2291.     else {
  2292.         ClearMenuStrip(Win);
  2293.         FreeMenus(menuStrip);
  2294.         FreeVisualInfo(visualInfo);
  2295.         free(NewMenus);
  2296.         menuStrip  = NULL;
  2297.         visualInfo = NULL;
  2298.         NewMenus   = NULL;
  2299.         AnzMenus = 0;
  2300.         AnzItems = 1;
  2301.         if (textFont) {
  2302.             CloseFont(textFont);
  2303.             textFont = NULL;
  2304.         }
  2305.         if (fontName) {
  2306.             free(fontName);
  2307.             fontName = NULL;
  2308.         }
  2309.     }
  2310.  
  2311.     Delay(3);
  2312. }
  2313.  
  2314.  
  2315. #if 0
  2316. int NumMenus;
  2317.  
  2318. static struct Menu DefaultMenu= {0, 0,0,TITWID,10, MENUENABLED,0,0};
  2319. static struct IntuiText DefaultIntuiText= {0,1,JAM2, 1,1,NULL,0,0};
  2320. static struct MenuItem DefaultMenuItem=
  2321.   {0, 0,0,ITEWID,0, HIGHCOMP|ITEMTEXT|ITEMENABLED,0,0,0,0,0,0};
  2322.  
  2323. struct Menu Menus[10];
  2324. char *MenuCommand[MAXMENUS][MAXMENUITEMS];
  2325.  
  2326. static void
  2327. install_menu( char *mav[], int mac )
  2328. {
  2329.     struct TextAttr *ta;
  2330.     struct Menu *m;
  2331.     struct MenuItem *mi, **pmi;
  2332.     struct IntuiText *it;
  2333.     int y, i, fonthei;
  2334.     char *p, *com;
  2335.  
  2336.     if( o_nowindow || !Win )
  2337.         return;
  2338.  
  2339.     if( mac>=MAXMENUITEMS )
  2340.         mac=MAXMENUITEMS-1;
  2341.  
  2342.     ClearMenuStrip( Win );
  2343.     Delay(3);
  2344.  
  2345.     if( NumMenus )
  2346.         Menus[NumMenus-1].NextMenu=Menus+NumMenus;
  2347.     m  =&Menus[NumMenus];
  2348.     *m =DefaultMenu;
  2349.     m->LeftEdge  = NumMenus*TITWID;
  2350.     m->MenuName  = strcpy(salloc(strlen(mav[0])+1),mav[0]);
  2351.     if( strlen(m->MenuName)>TITWID/8 )
  2352.         m->MenuName[TITWID/8+1]=0;
  2353.     DefaultIntuiText.ITextFont=ta=Win->WScreen->Font;
  2354.     DefaultMenuItem.Height=2+(fonthei=ta->ta_YSize);
  2355.  
  2356.     y=0;
  2357.     pmi=&m->FirstItem;
  2358.     for( i=1; i<mac; i++) {
  2359.         it =(void *)salloc(sizeof(struct IntuiText));
  2360.         *it=DefaultIntuiText;
  2361.         mi =(void *)salloc(sizeof(struct MenuItem ));
  2362.         *mi=DefaultMenuItem;
  2363.  
  2364.         com=NULL;
  2365.         if( p=index(mav[i],',')) {
  2366.             *p=0; com=++p;
  2367.             if( p=index(com,',')) {
  2368.                 *p=0;
  2369.                 mi->Command=p[1];
  2370.                 mi->Flags |=COMMSEQ;
  2371.             }
  2372.         }
  2373.  
  2374.         if( !com || !*com) {
  2375.             com=strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2376.             MenuCommand[NumMenus][i-1]=com;
  2377.             com+=strlen(com);
  2378.             *com++=13;
  2379.             *com=0;
  2380.         } else {
  2381.             MenuCommand[NumMenus][i-1]=strcpy(salloc(strlen(com)+1),com);
  2382.         }
  2383.  
  2384.         it->IText=(UBYTE *)strcpy(salloc(strlen(mav[i])+2),mav[i]);
  2385.  
  2386.         *pmi= mi;
  2387.         pmi = &mi->NextItem;
  2388.         mi->TopEdge = y;
  2389.         mi->ItemFill= (APTR)it;
  2390.  
  2391.         y+=DefaultMenuItem.Height;
  2392.     }
  2393.  
  2394.     NumMenus++;
  2395. MError:
  2396.     return;
  2397. }
  2398.  
  2399. void remove_menu()
  2400. {
  2401.     if (NumMenus>0) {
  2402.         struct MenuItem *mi, *nextmi;
  2403.         int i,j;
  2404.  
  2405.         for( i=0; i<NumMenus; i++ ) {
  2406.             for( mi=Menus[i].FirstItem,j=0 ; mi; mi=nextmi,j++ ) {
  2407.                 free( ((struct IntuiText *)mi->ItemFill)->IText );
  2408.                 free( ((struct IntuiText *)mi->ItemFill) );
  2409.                 nextmi=mi->NextItem;
  2410.                 free(mi);
  2411.                 free(MenuCommand[i][j]);
  2412.             }
  2413.         }
  2414.  
  2415.         NumMenus=0;
  2416.         set_menu();
  2417.     }
  2418. }
  2419.  
  2420. void set_menu()
  2421. {
  2422.     if (o_nowindow || !Win)
  2423.         return;
  2424.  
  2425.     if (NumMenus>0)
  2426.         SetMenuStrip(Win,Menus);
  2427.     else
  2428.         ClearMenuStrip(Win);
  2429.  
  2430.     Delay(3);
  2431. }
  2432. #endif
  2433.  
  2434. int
  2435. do_getenv( void )
  2436. {
  2437.     char buf[256], *val=buf;
  2438.  
  2439.     if( ac!=3 && ac!=2 ) {
  2440.         show_usage( NULL );
  2441.         return 20;
  2442.     }
  2443.     /* AMK: OS20-GetVar replaces ARP-Getenv */
  2444.     if( GetVar(av[ac-1],buf,256,GVF_GLOBAL_ONLY|GVF_BINARY_VAR) < 0L )
  2445.         val="";
  2446.  
  2447.     if( ac==2 )
  2448.         printf( "%s\n", val );
  2449.     else
  2450.         set_var( LEVEL_SET, av[1], val );
  2451.     return 0;
  2452. }
  2453.  
  2454. int
  2455. do_setenv( void )
  2456. {
  2457.     if( ac!=3 ) {
  2458.         show_usage( NULL );
  2459.         return 20;
  2460.     } else
  2461.         setenv( av[1], av[2] );
  2462.     return 0;
  2463. }
  2464.  
  2465. char **
  2466. read_name( char *name, int *ac )
  2467. {
  2468.     FILE *file;
  2469.     char **av=NULL;
  2470.  
  2471.     *ac=0;
  2472.     if( file=name ? fopen( name, "r") : stdin ) {
  2473.         av=read_file( file, ac );
  2474.         if( name ) fclose( file );
  2475.     } else 
  2476.         pError( name );
  2477.     return av;
  2478. }
  2479.  
  2480.  
  2481. char **
  2482. read_file( FILE *file, int *ac )
  2483. {
  2484.     int buflen=4096, lines=0, i, offs, got=0;
  2485.     char *buf, *tmp, *ptr, **lineptr;
  2486.  
  2487.     if( !(buf=ptr=DosAllocMem( buflen )))
  2488.         goto error;
  2489.     do {
  2490.         while( ptr+400 < buf+buflen && (got=myfgets(ptr, file)) && !dobreak())
  2491.             ptr+=strlen(ptr)+1, lines++;
  2492.         if( ptr+256 < buf+buflen ) {
  2493.             offs=ptr-buf;
  2494.             if( !(tmp=DosAllocMem( buflen*2 )))
  2495.                 goto error;
  2496.             memcpy( tmp, buf, buflen );
  2497.             DosFreeMem( buf );
  2498.             buflen*=2, buf=tmp;
  2499.             ptr=buf+offs;
  2500.         }
  2501.     } while( got && !dobreak());
  2502.     if( !(lineptr=(char **)DosAllocMem( (lines+1)*sizeof( char * ))))
  2503.         goto error;
  2504.     *lineptr++=buf;
  2505.     for( ptr=buf, i=0; i<lines; i++ ) {
  2506.         lineptr[i]=ptr;
  2507.         ptr+=strlen(ptr)+1;
  2508.     }
  2509.     *ac=lines;
  2510.     return lineptr;
  2511.  
  2512. error:
  2513.     if( buf ) DosFreeMem( buf );
  2514.     fprintf( stderr, "Out of memory\n" );
  2515.     *ac=0;
  2516.     return NULL;
  2517. }
  2518.  
  2519. void
  2520. free_file( ptr )
  2521.     char **ptr;
  2522. {
  2523.     if( ptr-- ) {
  2524.         if( *ptr )
  2525.             DosFreeMem( *ptr );
  2526.         DosFreeMem(ptr);
  2527.     }
  2528. }
  2529.  
  2530.  
  2531. do_qsort( void )
  2532. {
  2533.     char **lineptr;
  2534.     int  lines, i;
  2535.  
  2536.     if( ac==1 ) {
  2537.         lineptr=read_file( stdin, &lines);
  2538.         DirQuickSort( lineptr, lines, cmp, options&1, 0 );
  2539.         prepscroll(0);
  2540.         for( i=0; i<lines && !dobreak(); i++ ) {
  2541.             quickscroll();
  2542.             puts( lineptr[i] );
  2543.         }
  2544.         free_file( lineptr );
  2545.     } else
  2546.         ierror( NULL,506 );
  2547.     return 0;
  2548. }
  2549.  
  2550. extern int w_width;
  2551.  
  2552. do_truncate( void )
  2553. {
  2554.     char buf[256];
  2555.     int  w=newwidth(), c;
  2556.     char *ptr;
  2557.  
  2558.     if( ac==2 )
  2559.         w=atoi( av[1] );
  2560.  
  2561.     prepscroll(0);
  2562.     while( myfgets(buf,stdin) && !dobreak() ) {
  2563.         for( c=0, ptr=buf; *ptr && c<w; ptr++ )
  2564.             if( *ptr=='\t' )
  2565.                 c+=8-(c&7);
  2566.             else if( *ptr==27 ) {
  2567.                 while( *ptr<'@' )
  2568.                     ptr++;
  2569.             } else 
  2570.                 c++;
  2571.         *ptr=0;
  2572.         quickscroll();
  2573.         puts(buf);
  2574.     }
  2575.     return 0;
  2576. }
  2577.  
  2578. int
  2579. do_readfile( void )
  2580. {
  2581.     char **rav, *str=NULL, *file=NULL;
  2582.     int rac;
  2583.  
  2584.     if( ac>2 ) file=av[2];
  2585.     if( rav=read_name( file, &rac ) ) { 
  2586.         if( str= compile_av( rav, 0, rac, 0xA0, 0 ) )
  2587.             set_var( LEVEL_SET, av[1], str );
  2588.         free_file( rav );
  2589.     }
  2590.     return str ? 0 : 20;
  2591. }
  2592.  
  2593. void
  2594. foreach( char **s, int (*func)(char *s) )
  2595. {
  2596.     char *str;
  2597.  
  2598.     for( ;; ) {
  2599.         str=*s;
  2600.         if( !(*s=index(*s,0xA0)))
  2601.             break;
  2602.         **s=0;
  2603.         (*func)(str);
  2604.         *(*s)++=0xA0;
  2605.         if( breakcheck())
  2606.             return;
  2607.     }
  2608.     (*func)(str);
  2609. }
  2610.  
  2611. int
  2612. do_writefile( void )
  2613. {
  2614.     char *ptr;
  2615.  
  2616.     if( !(ptr=get_var(LEVEL_SET,av[1])))
  2617.         { fprintf(stderr,"Undefined variable %s\n",av[1]); return 20; }
  2618.  
  2619.     foreach( &ptr, puts );
  2620.  
  2621.     return 0;
  2622. }
  2623.  
  2624. int
  2625. do_split( void )
  2626. {
  2627.     int i;
  2628.     char *val, *gap, *oldval;
  2629.  
  2630.     if( !(val=get_var( LEVEL_SET, av[1] )))
  2631.         { fprintf( stderr, "undefined variable %s\n", av[1] ); return 20; }
  2632.     oldval=val=strcpy(salloc(strlen(val)+1),val);
  2633.     for( i=2; i<ac-1; i++ ) {
  2634.         if( gap=index(val,0xA0 )) *gap=0;
  2635.         set_var( LEVEL_SET, av[i], val );
  2636.         val="";
  2637.         if( gap ) *gap=0xA0, val=gap+1;
  2638.     }
  2639.     set_var( LEVEL_SET, av[ac-1], val );
  2640.     free(oldval);
  2641.     return 0;
  2642. }
  2643.  
  2644. char *
  2645. copyof( char *str )
  2646. {
  2647.     return strcpy(salloc(strlen(str)+1),str);
  2648. }
  2649.  
  2650. int
  2651. do_class( char *avline )
  2652. {
  2653.     CLASS *new;
  2654.  
  2655.     if( options&1 ) {
  2656.         avline=next_word(avline);
  2657.         for( new=CRoot,CRoot=NULL; new; new=new->next )
  2658.             Free(new);
  2659.     }
  2660.  
  2661.     if( ac==1 ) {
  2662.         for( new=CRoot; new; new=new->next )
  2663.             printf("%s\n",new->name);
  2664.         return 0;
  2665.     }
  2666.  
  2667.     avline=next_word(avline);
  2668.     if(!(new=malloc( strlen(avline)+5)))
  2669.         ierror( NULL, 512 );
  2670.     else {
  2671.         new->next=NULL;
  2672.         strcpy( new->name,avline );
  2673.         if( CRoot )
  2674.             LastCRoot->next=new;
  2675.         else 
  2676.             CRoot=new;
  2677.         LastCRoot=new;
  2678.     }
  2679.     return 0;
  2680. }
  2681.  
  2682. do_getcl( void )
  2683. {
  2684.     char *s=getclass(av[1]);
  2685.     if( s ) printf("%s\n",s);
  2686.     return 0;
  2687. }
  2688.  
  2689. do_action( char *argline )
  2690. {
  2691.     char *args, err;
  2692.     int abort=options&1;
  2693.  
  2694.     args=compile_av( av,3,ac,' ',0 );
  2695.     err=doaction(av[2],av[1],args);
  2696.     if( !abort )
  2697.         if( err==9 )     ierror(av[2], 205 );
  2698.         else if(err==10) fprintf(stderr,"Can't identify %s\n", av[2] );
  2699.         else if(err==11) fprintf(stderr,"Can't '%s' this file\n",av[1] );
  2700.         else if(err==12) fprintf(stderr,"Error executing the program to '%s' this file\n",av[1] );
  2701.     free(args);
  2702.     return abort ? !err : err;
  2703. }
  2704.  
  2705.  
  2706.